#include "packing_graphics.h"
#include "polygon_triangulation.h"

namespace Field_packing
{
	static const GLfloat pgn_fill_color[] = {0.7f, 0.7f, 0.7f};
	static const GLfloat pgn_highlight_color[] = {0.0f, 0.9f, 0.0f};
	//static const GLfloat pgn_large_room_color[] = {0.486f, 0.761f, 0.929f};
	//static const GLfloat triangulation_edge_color[] = {0.85f, 0.0f, 0.0f};
	//static const GLfloat voronoi_edge_color[] = {0.0f, 0.0f, 0.85f};
	//static const GLfloat cat_edge_color[] = {0.85f, 0.0f, 0.85f};
	static const GLfloat c1 = 0.35f ;
	static const GLfloat c2 = 0.5f ;
	static const GLfloat c3 = 1.0f ;
	static GLfloat color_table[24][3] = 
	{
		{c3, c2, c2},{c2, c3, c2},{c2, c2, c3},{c2, c3, c3},{c3, c2, c3},{c3, c3, c2},
		{c1, c2, c2},{c2, c1, c2},{c2, c2, c1},{c2, c1, c1},{c1, c2, c1},{c1, c1, c2},
		{c1, c3, c3},{c3, c1, c3},{c3, c3, c1},{c3, c1, c1},{c1, c3, c1},{c1, c1, c3},
		{c1, c2, c3},{c1, c3, c2},{c2, c1, c3},{c2, c3, c1},{c3, c1, c2},{c3, c2, c1}
	} ;

	static int random_color_index_ = 0 ;
	static void gl_random_color() {
		glColor3f(
			color_table[random_color_index_][0], 
			color_table[random_color_index_][1], 
			color_table[random_color_index_][2]
		) ;
		random_color_index_ = (random_color_index_ + 1) % 12 ;
	}
	static void gl_random_color(int index) {
		random_color_index_ = index % 12 ;
		gl_random_color() ;
	}
	static void gl_randomize_colors() {
		random_color_index_ = 0 ;
	}
	Packing_graphics::Packing_graphics(Packer* _packer) 
		: packer(_packer), 
		show_polygons(GL_TRUE), show_circles(GL_TRUE), show_bd_box(GL_TRUE),
		show_sampling_pnts(GL_TRUE), show_distance_field(GL_TRUE), store_inter_result(GL_FALSE),
		show_delaunay(GL_FALSE), show_holes(GL_TRUE), show_CAT(GL_FALSE), show_vacancy(GL_TRUE), 
		vacant_group_no(-1), highlight_no(-1)
	{
	}
	Packing_graphics::~Packing_graphics()
	{

	}
	void Packing_graphics::draw()
	{
		static int img_idx = 0;
		const int img_step = 5;

		glUseProgramObjectARB(0);
		
		//gl_randomize_colors();

		//std::cout << "Drawing...\n";
		
		if (show_bd_box)
			packer->rbox->gl_draw();
		if (show_polygons)
		{
			if (!show_distance_field || highlight_no < 0 || highlight_no >= packer->polygon_set.size())
			{
				//draw_polygons();
				if (packer->sync_draw)
					sync_draw_polygons();
				else
					draw_polygons();
			}
			else if (show_distance_field && highlight_no >=0 && highlight_no < packer->polygon_set.size())
			{
				glColor3fv(pgn_fill_color);
				packer->polygon_set[highlight_no]->gl_draw(pgn_fill_color);
			}
		}
		if (store_inter_result && packer->sync_draw && !sync_polygons.empty())
		{
			if (img_idx%img_step == 0)
			{
				std::ostringstream oss;
				oss<<"./steps/"<<img_idx/img_step<<".png";
				copy_image_to_png(oss.str().c_str());
			}
			img_idx++;
		}

		if (show_delaunay)
			packer->pt.draw_triangulation();
		
		if (show_holes)
		{
			glColor3f(0.8f, 0.0f, 0.0f);
			glLineWidth(2.0f);
			glBegin(GL_LINES);
			for (size_t i = 0; i < packer->holes.size(); i++)
			{
				const Packer::Hole& hl = packer->holes.at(i);
				for (std::list<Packing_polygon::Segment_2>::const_iterator it = hl.segments.begin(); it != hl.segments.end(); ++it)
				{
					glVertex2d(it->source().x(), it->source().y());
					glVertex2d(it->target().x(), it->target().y());
				}
			}
			glEnd();
		}
		if (show_CAT)
		{
			//packer->pt.draw_CAT();
			packer->pt.draw_polygonal_CAT();
		}
		if (show_vacancy)
		{
			if (vacant_group_no >= 0) 
				packer->draw_vacant_space(vacant_group_no%packer->groups.size());
		}
		//if (show_sampling_pnts)
		//packer->db_cps->draw_sample_pnts();
		//if (show_distance_field && highlight_no >= 0 && highlight_no < packer->polygon_set.size())
		//	packer->dfg->gl_draw(highlight_no);
				//packer->dfg->gl_draw_local_field(highlight_no);
	}

	void Packing_graphics::draw_polygons()
	{
		//std::for_each(packer->polygon_set.begin(), packer->polygon_set.end(), std::bind2nd(std::mem_fun(&Packing_polygon::gl_draw), pgn_fill_color));
		for (unsigned int i = 0; i < packer->polygon_set.size(); i++)
		{
			glColor3fv(pgn_fill_color);
			packer->polygon_set[i]->gl_draw(pgn_fill_color);
		}
	}

	void Packing_graphics::sync_draw_polygons()
	{
		if (!packer->trans_queue.empty()) 
		{
		//	draw_polygons();
		//}
		//else
		//{
			//std::cout<<"breakpoint 1\n";
			std::vector<Parameter> para;
			packer->trans_queue.pop_front(para);
			sync_polygons.clear();
			sync_polygons.reserve(packer->polygon_set.size());
			for (size_t i = 0; i < packer->polygon_set.size(); i++)
			{
				sync_polygons.push_back(*packer->polygon_set.at(i));
			}
			for (size_t i = 0; i < sync_polygons.size(); i++)
				sync_polygons[i].transform(para[i]);
			//std::cout<<"breakpoint 2\n";

			//std::cout<<"breakpoint 3\n";
			//packer->trans_queue.pop();
			//std::cout<<"breakpoint 4\n";
		}
		for (unsigned int i = 0; i < sync_polygons.size(); i++)
		{
			glColor3fv(pgn_fill_color);
			sync_polygons[i].gl_draw(pgn_fill_color);
		}
	}
}
